package com.atguigu.tingshu.album.api;

import com.atguigu.tingshu.album.config.MinioConstantProperties;
import com.atguigu.tingshu.common.result.Result;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.UUID;

/**
 * 文件上传管理接口
 *
 * @author Taeyang
 * @date 2025-04-23
 */
@Tag(name = "上传管理接口")
@RestController
@RequestMapping("/api/album")
public class FileUploadApiController {

    private final MinioClient minioClient;
    private final MinioConstantProperties minioConstantProperties;

    @Autowired
    public FileUploadApiController(MinioConstantProperties minioConstantProperties, MinioClient minioClient) {
        this.minioClient = minioClient;
        this.minioConstantProperties = minioConstantProperties;
    }

    /**
     * Minio文件上传
     * 注解 @SneakyThrows：简化异常处理逻辑，允许方法直接抛出受检异常而无需显式使用try-catch块或在方法签名中声明throws。
     * 注解 @RequestParam：用于将 HTTP 请求中的查询参数（query parameter）或表单数据绑定到方法参数上。适用于处理简单的键值对参数。
     * 注解 @RequestBody：用于将 HTTP 请求的正文（body）绑定到方法参数上。适用于处理复杂的 JSON 或 XML 数据。
     *
     * @param file 文件
     * @return Result<String>
     */
    @SneakyThrows
    @PostMapping("/fileUpload")
    public Result<String> fileUpload(@RequestParam("file") MultipartFile file) {

        // 判断桶是否存在，不存在则需要创建
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioConstantProperties.getBucketName()).build())) {
            // 不存在时候创建桶
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioConstantProperties.getBucketName()).build());
        }
        // 随机生成一个文件名
        // 使用 replace("-", "") 方法移除字符串中的所有连字符 -，确保生成的文件名不含特殊字符。
        String fileName = UUID.randomUUID().toString().replace("-", "");
        // 使用客户端对象上传图片文件
        minioClient.putObject(PutObjectArgs.builder()
                // 文件数据
                .stream(file.getInputStream(), file.getSize(), -1)
                // 文件类型
                .contentType(file.getContentType())
                // 文件存储桶位置
                .bucket(minioConstantProperties.getBucketName())
                // 文件名
                .object(fileName)
                .build());
        // 拼接访问的地址：Minio的地址 + 桶名 + 文件名
        String url = minioConstantProperties.getEndpointUrl() + "/" + minioConstantProperties.getBucketName() + "/" + fileName;
        // 返回文件的访问地址
        return Result.ok(url);
    }

}
